#pragma once
#include <chrono>
#include <cstdio>
#include <string.h>
#include <string>

struct trace_timestamp
{
    trace_timestamp()
    {
        nano_ts_ = std::chrono::nanoseconds(std::chrono::system_clock::now().time_since_epoch()).count();
    }

    std::string to_string() const
    {
        std::time_t t = nano_ts_ / 1000000000;
        struct tm   result;
        localtime_r(&t, &result);
        auto year_   = result.tm_year + 1900;
        auto month_  = result.tm_mon + 1;
        auto day_    = result.tm_mday;
        auto hour_   = result.tm_hour;
        auto minute_ = result.tm_min;
        auto second_ = result.tm_sec;
        char buf[64] = {0};
        snprintf(buf, sizeof(buf), "%04d-%02d-%02d_%02d:%02d:%02d.%09lld", year_, month_, day_, hour_, minute_, second_,
                 nano_ts_ % 1000000000);

        return std::string(buf);
    }

  private:
    long long nano_ts_;
};

#define BASENAME(file) (strrchr(file, '/') ? (strrchr(file, '/') + 1) : file)

#define TRACE_DEBUG(fmt, args...)                                                                                      \
    do {                                                                                                               \
        printf("%s %s:%d(%s): " fmt "\n", trace_timestamp().to_string().c_str(), BASENAME(__FILE__), __LINE__,         \
               __FUNCTION__, ##args);                                                                                  \
        fflush(stdout);                                                                                                \
                                                                                                                       \
    } while (0)

#define TRACE_SYSTEM(fmt, args...)                                                                                     \
    do {                                                                                                               \
        printf("%s %s:%d(%s)[%s]: " fmt "\n", trace_timestamp().to_string().c_str(), BASENAME(__FILE__), __LINE__,     \
               __FUNCTION__, strerror(errno), ##args);                                                                 \
        fflush(stdout);                                                                                                \
                                                                                                                       \
    } while (0)
